﻿using System;
using System.Collections.Generic;
using NHibernate;
using NHibernate.Criterion;
using Neturion.Dados;
using Neturion.IRepositorios;

namespace Neturion.Repositorios
{
    public class RepositorioFornecedor : IRepositorioFornecedor
    {
        public Fornecedor Inserir(Fornecedor fornecedor)
        {
            fornecedor.InicioVigenciaFornecedor = fornecedor.InicioVigenciaFornecedor.HasValue
                                                         ? fornecedor.InicioVigenciaFornecedor.Value.Date
                                                         : fornecedor.InicioVigenciaFornecedor;

            fornecedor.FimVigenciaFornecedor = fornecedor.FimVigenciaFornecedor.HasValue
                                                         ? fornecedor.FimVigenciaFornecedor.Value.Date
                                                         : fornecedor.FimVigenciaFornecedor;

            fornecedor.DataCadastro = fornecedor.DataCadastro.Date;
           
            GerenciadorBDConfigs.Instance.SessaoAtual().Save(fornecedor);
            return fornecedor;
        }

        public Fornecedor Atualizar(Fornecedor fornecedor)
        {
            Fornecedor tmpFornecedor = ObterPorId(fornecedor.FornecedorId);
            // Atribuicao dos valores do objeto da memoria para o objeto obtido no banco de dados
            tmpFornecedor.Pessoa = fornecedor.Pessoa;
            tmpFornecedor.Codigo = fornecedor.Codigo;
            tmpFornecedor.DataCadastro = fornecedor.DataCadastro.Date;
            tmpFornecedor.RamoAtividade = fornecedor.RamoAtividade;
            tmpFornecedor.Cnae = fornecedor.Cnae;
           
            tmpFornecedor.InicioVigenciaFornecedor = fornecedor.InicioVigenciaFornecedor.HasValue
                                                         ? fornecedor.InicioVigenciaFornecedor.Value.Date
                                                         : fornecedor.InicioVigenciaFornecedor;
            tmpFornecedor.FimVigenciaFornecedor = fornecedor.FimVigenciaFornecedor.HasValue
                                                         ? fornecedor.FimVigenciaFornecedor.Value.Date
                                                         : fornecedor.FimVigenciaFornecedor;
            
            tmpFornecedor.ObservacaoFornecedor = fornecedor.ObservacaoFornecedor;

            tmpFornecedor.NeturionLog = fornecedor.NeturionLog;

            tmpFornecedor.ListaProdutos.Clear();
            foreach (Produto produto in fornecedor.ListaProdutos)
            {
                tmpFornecedor.AdicionarProduto(produto);
            }

            GerenciadorBDConfigs.Instance.SessaoAtual().Merge(tmpFornecedor);
            return tmpFornecedor;
        }

        public void Excluir(Fornecedor fornecedor)
        {
            GerenciadorBDConfigs.Instance.SessaoAtual().Delete(fornecedor);
        }

        public IList<Fornecedor> ObterTodos()
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Fornecedor));
            return criteria.List<Fornecedor>() as List<Fornecedor>;
        }

        public IList<Fornecedor> ObterTodos(int inicio, int quantidade, int quantidadeMinima, string nomeRazaoSocial, string apelidoFantasia, string nomeReduzido, string cpfCnpj, Midia midia, EnumTipoPessoa enumTipoPessoa, RamoAtividade ramoAtividade, Cnae cnae, DateTime? dataNascimentoAberturaDe, DateTime? dataNascimentoAberturaAte, DateTime? cadastroDe, DateTime? cadastroAte, DateTime? inicioVigenciaDe, DateTime? inicioVigenciaAte, DateTime? fimVigenciaDe, DateTime? fimVigenciaAte)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Fornecedor))
                .SetFirstResult(inicio).SetMaxResults(quantidade)
                .CreateAlias("Pessoa", "Pessoa");
            
            if(enumTipoPessoa.GetHashCode() != -1)
            {
                criteria.Add(Restrictions.Eq("Pessoa.EnumTipoPessoa", enumTipoPessoa));
            }

            if (!String.IsNullOrEmpty(nomeRazaoSocial))
            {
                
                criteria.Add(Restrictions.Like("Pessoa.NomeRazaoSocial", nomeRazaoSocial, MatchMode.Anywhere));
            }

            if (!String.IsNullOrEmpty(apelidoFantasia))
            {
                
                criteria.Add(Restrictions.Like("Pessoa.ApelidoFantasia", apelidoFantasia, MatchMode.Anywhere));
            }

            if (!String.IsNullOrEmpty(nomeReduzido))
            {
                criteria.Add(Restrictions.Like("Pessoa.NomeReduzido", nomeReduzido, MatchMode.Anywhere));
            }

            if (!String.IsNullOrEmpty(cpfCnpj))
            {
                criteria.Add(Restrictions.Eq("Pessoa.CpfCnpj", cpfCnpj));
            }

            if (midia != null)
            {
                criteria.Add(Restrictions.Eq("Pessoa.Midia", midia));
            }

            if (dataNascimentoAberturaDe.HasValue)
            {
                criteria.Add(dataNascimentoAberturaAte.HasValue
                    ? Restrictions.Between("Pessoa.DataNascimentoAbertura", dataNascimentoAberturaDe.Value.Date, dataNascimentoAberturaAte.Value.Date)
                    : Restrictions.Eq("Pessoa.DataNascimentoAbertura", dataNascimentoAberturaDe.Value.Date));
            }

            if(ramoAtividade != null)
            {
                criteria.Add(Restrictions.Eq("RamoAtividade", ramoAtividade));
            }

            if (cnae != null)
            {
                criteria.Add(Restrictions.Eq("Cnae", cnae));
            }

            if (cadastroDe.HasValue)
            {
                criteria.Add(cadastroAte.HasValue
                    ? Restrictions.Between("DataCadastro", cadastroDe.Value.Date, cadastroAte.Value.Date)
                    : Restrictions.Eq("DataCadastro", cadastroDe.Value.Date));
            }

            if (inicioVigenciaDe.HasValue)
            {
                criteria.Add(inicioVigenciaAte.HasValue
                    ? Restrictions.Between("InicioVigenciaFornecedor", inicioVigenciaDe.Value.Date, inicioVigenciaAte.Value.Date)
                    : Restrictions.Eq("InicioVigenciaFornecedor", inicioVigenciaDe.Value.Date));
            }

            if (fimVigenciaDe.HasValue)
            {
                criteria.Add(fimVigenciaAte.HasValue
                    ? Restrictions.Between("FimVigenciaFornecedor", fimVigenciaDe.Value.Date, fimVigenciaAte.Value.Date)
                    : Restrictions.Eq("FimVigenciaFornecedor", fimVigenciaDe.Value.Date));
            }

            return criteria.List<Fornecedor>() as List<Fornecedor>;
        }

        public Fornecedor ObterPorId(int id)
        {
            return GerenciadorBDConfigs.Instance.SessaoAtual().Get<Fornecedor>(id);
        }

        public Fornecedor ObterPorCodigo(string codigo)
        {
             ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Fornecedor))
                 .Add(Restrictions.Eq("Codigo",codigo));
            return criteria.UniqueResult<Fornecedor>();
        }

        public Fornecedor ObterPorCpfCnpj(string cpfCnpj)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Fornecedor))
                .CreateAlias("Pessoa","Pessoa")
                .Add(Restrictions.Eq("Pessoa.CpfCnpj", cpfCnpj));
            return criteria.UniqueResult<Fornecedor>();
        }

        public Fornecedor ObterPorPessoa(Pessoa pessoa)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Fornecedor))
                .Add(Restrictions.Eq("Pessoa", pessoa));
            return criteria.UniqueResult<Fornecedor>();
        }

        public IList<Fornecedor> ObterPorNome(int inicio, int quantidade, int quantidadeMinima, string nome)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            IList<OrgaoExpedidor> list;
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Fornecedor))
               .SetFirstResult(inicio).SetMaxResults(quantidade);
            
            criteria.CreateAlias("Pessoa", "Pessoa").Add(Restrictions.Like("Pessoa.NomeRazaoSocial", nome, MatchMode.Anywhere));
            return criteria.List<Fornecedor>() as List<Fornecedor>;
        }
        
        public IList<Fornecedor> ObterPorRamoAtividade(RamoAtividade ramoAtividade)
        {
             ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Fornecedor))
                 .Add(Restrictions.Eq("RamoAtividade",ramoAtividade));
            return criteria.List<Fornecedor>() as List<Fornecedor>;
        }
        
        public IList<Fornecedor> ObterPorCnae(Cnae cnae)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Fornecedor))
                .Add(Restrictions.Eq("Cnae",cnae));
            return criteria.List<Fornecedor>() as List<Fornecedor>;
        }

        public int ObterUltimoIdCodigoInteiro()
        {
            string[] literal = new string[] 
                {"a","b","c","d","e","f","g","h","i","j"
                ,"l","m","n","o","p","q","r","s","t","u","v","x","z","y"
                ,"w"};

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Fornecedor)).SetMaxResults(1);

            for (int i = 0; i <= literal.Length - 1; i++)
            {
                criteria.Add(Restrictions.Not(Restrictions.Like("Codigo", literal[i], MatchMode.Anywhere)));
            }

            criteria.AddOrder(Order.Desc("FornecedorId"));


            Fornecedor fornecedor = criteria.UniqueResult<Fornecedor>();
            int ultimoCodigo = fornecedor != null ? fornecedor.FornecedorId : 0;

            return ultimoCodigo;
        }
    }
}